﻿using System;
using Adaptive.Agrona;
using Adaptive.Agrona.Concurrent;

using Unity.Type.BinaryType;

namespace Unity.Type
{
    public class MetadataEDeserializer : IUnityDeserializer<MetadataE>
    {
        private static readonly MessageHeader MessageHeader = new MessageHeader();
        private static readonly MetadataE MetadataEDecoder = new MetadataE();

        private const int MessageLength = MessageHeader.Size + MetadataE.BlockLength;
        private readonly IMutableDirectBuffer _decodeBuffer = new UnsafeBuffer(new byte[MessageLength]);

        private void Wrap()
        {
            MessageHeader.Wrap(this._decodeBuffer, 0, MessageHeader.EncodingSchemaVersion);
            MetadataEDecoder.WrapForDecode(this._decodeBuffer, MessageHeader.Size, 
                MetadataE.BlockLength, MessageHeader.Version);
        }

        private string GetCsiId()
        {
            return MetadataEDecoder.GetCsiId();
        }

        private byte GetDelimiter()
        {
            return MetadataEDecoder.Delimiter;
        }

        private byte GetSpecVersion()
        {
            return MetadataEDecoder.SpecVersion;
        }

        private string GetRandom()
        {
            return MetadataEDecoder.GetRandom();
        }

        private string GetCounter()
        {
            return MetadataEDecoder.GetCounter();
        }

        private int GetChangerCsiId()
        {
            return MetadataEDecoder.ChangerCsiId;
        }

        private EntityType GetEntityType()
        {
            return MetadataEDecoder.EntityType;
        }

        private EventType GetEventType()
        {
            return MetadataEDecoder.EventType;
        }

        private long GetVersion()
        {
            return MetadataEDecoder.Version;
        }

        private long GetTimestamp()
        {
            return MetadataEDecoder.Timestamp;
        }

        private long GetVersionDelete()
        {
            return MetadataEDecoder.VersionDelete;
        }

        private int GetFormatVer()
        {
            return MetadataEDecoder.FormatVer;
        }

        private MetadataE InternalDeserialize()
        {
            try
            {
                Wrap();
                MetadataE metadata = new MetadataE();
                metadata.SetCsiId(GetCsiId());
                metadata.Delimiter = GetDelimiter();
                metadata.SpecVersion = GetSpecVersion();
                metadata.SetRandom(GetRandom());
                metadata.SetCounter(GetCounter());
                metadata.ChangerCsiId = GetChangerCsiId();
                metadata.EntityType = GetEntityType();
                metadata.EventType = GetEventType();
                metadata.Version = GetVersion();
                metadata.Timestamp = GetTimestamp();
                metadata.VersionDelete = GetVersionDelete();
                metadata.FormatVer = GetFormatVer();
                return metadata;
            }
            catch (Exception exception)
            {
                Console.Error.WriteLine(exception);
                return null;
            }
        }
        
        public MetadataE Deserialize(byte[] data)
        {
            this._decodeBuffer.Wrap(data);
            return InternalDeserialize();
        }
    }
}
